var assert    = require('assert'),
    utility   = require('system/utility'),
    Auditable = require('system/auditable');

AuditableTests = (function () {
	var AuditableTests = function() {


		return {
			'#constructor' : {
				'settings should be cloned' : function() {
					var settings  = { history : [] },
					    auditable = new Auditable(settings);

					settings.history = [1,2,3,4];

					assert.deepEqual(auditable.history, []);
				}
			},
			'#history': {
				'history should be read only' : function() {
					var settings  = { name : 'test', history : [] },
					    auditable = new Auditable(settings);

					settings.history  = 'fdsa';
					auditable.history = 'asdf';
					
					assert.deepEqual(auditable.history, []);
				}
			},
			'#addHistory(user, data)' : {
				'calling add history should immediately add to the history array' : function() {
					var auditable = new Auditable({ name : 'test' });

					auditable.addHistory({ userName : 'gkimmy' }, { type: 1, name: 'greg' });

					assert.equal(auditable.history.length, 1);
					assert.deepEqual(auditable.history[0].user, { userName : 'gkimmy' });
					assert.deepEqual(auditable.history[0].data, { type: 1, name: 'greg' });
					assert.ok(utility.now() - auditable.history[0].timestampUtc < 5);
				},
				'user objects on history items should be referential' : function() {
					var auditable = new Auditable({ name : 'test' });
					var user      = { userName : 'gkimmy' };

					auditable.addHistory(user, { type: 1, name: 'greg' });

					user.name = 'greg';

					assert.equal(auditable.history[0].user, user);
				}
			},
			'#commit(user)' : {
				'if nothing changes then commit should do nothing' : function() {
					var auditable = new Auditable({ name : 'test' });

					Object.defineProperty(auditable, 'name', {
						get: function() {
							return this._data.name;
						},
						set : function(value) {
							this._data.name = value;
						}
					});

					auditable.commit();

					assert.equal(auditable.history.length, 0);
				},
				'calling commit with changes should add a history item' : function() {
					var auditable = new Auditable({ name : 'test' });

					Object.defineProperty(auditable, 'name', {
						get: function() {
							return this._data.name;
						},
						set : function(value) {
							this._data.name = value;
						}
					});

					Object.defineProperty(auditable, 'state', {
						get: function() {
							return this._data.state;
						},
						set : function(value) {
							this._data.state = value;
						}
					});

					auditable.name = 'greg';

					assert.equal(auditable.history.length, 0);

					auditable.commit({ userName : 'gkimmy' });

					assert.equal(auditable.history.length, 1);
					assert.deepEqual(auditable.history[0].data, { name : 'greg' });

					auditable.state = 'TX';

					assert.equal(auditable.history.length, 1);
					assert.deepEqual(auditable.history[0].data, { name : 'greg' });

					auditable.commit({ userName : 'gskiba' });

					assert.equal(auditable.history.length, 2);
					assert.deepEqual(auditable.history[0].data, { name : 'greg' });
					assert.deepEqual(auditable.history[1].data, { state : 'TX' });
				},
				'calling commit twice with changes should only add one item' : function() {
					var auditable = new Auditable({ name : 'test' });

					Object.defineProperty(auditable, 'name', {
						get: function() {
							return this._data.name;
						},
						set : function(value) {
							this._data.name = value;
						}
					});

					auditable.name = 'greg';
					auditable.commit();

					assert.equal(auditable.history.length, 1);
					assert.deepEqual(auditable.history[0].data, { name : 'greg' });
					auditable.commit();

					assert.equal(auditable.history.length, 1);
					assert.deepEqual(auditable.history[0].data, { name : 'greg' });
				}
			}
		}
	};

	return AuditableTests;
})();

// Hook into commonJS module systems
if (typeof module !== 'undefined' && "exports" in module) {
  module.exports = AuditableTests;
}